﻿package com.zouloux.persp 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import org.papervision3d.cameras.Camera3D;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.render.BasicRenderEngine;
	import org.papervision3d.scenes.Scene3D;
	import org.papervision3d.view.Viewport3D;
	
	/**
	 * ...
	 * @author ZoulouX
	 */
	public class PaperEngine extends Sprite
	{
		// La scène 3D
		protected var _scene			:Scene3D;
		
		// Le moteur de rendu
		protected var _render			:BasicRenderEngine;
		
		// La vue
		protected var _viewport			:Viewport3D;
		
		// Les caméras
		protected var _cameras			:Array						= [];
		
		// La caméra séléctionnée
		protected var _selectedCamera	:uint						= 0;
		
		// Le centre de la scene
		protected var _center			:DisplayObject3D;
		
		
		// Les getters
		public function get scene():Scene3D
		{
			return _scene;
		}
		public function get render():BasicRenderEngine
		{
			return _render;
		}
		public function get viewport():Viewport3D
		{
			return _viewport;
		}
		public function get camera():Camera3D
		{
			return _cameras[_selectedCamera];
		}
		public function get cameras():Array
		{
			return _cameras;
		}
		public function get selectedCamera():uint
		{
			return _selectedCamera;
		}
		public function get center():DisplayObject3D
		{
			return _center;
		}
		
		
		// Les setters
		public function set scene(value:Scene3D):void 
		{
			_scene = value;
		}
		public function set render(value:BasicRenderEngine):void 
		{
			_render = value;
		}
		public function set viewport(value:Viewport3D):void 
		{
			_viewport = value;
		}
		public function set cameras(value:Array):void 
		{
			_cameras = value;
		}
		public function set selectedCamera(value:uint):void 
		{
			if (value < _cameras.length)
			{
				_selectedCamera = _cameras.length - 1;
				throw new Error("This camera index don't exists");
			}
			else
				_selectedCamera = value;
		}
		
		
		// Le constructeur
		public function PaperEngine (pWidth:int = 0, pHeight:int = 0, pAutoCreateCamera:Boolean = false)
		{
			if (pWidth != 0 && pHeight != 0)
				init(pWidth, pHeight);
			
			if (pAutoCreateCamera)
				addCamera(new Camera3D());
		}
		
		// Initialiser le moteur 3D
		public function init (pWidth:int, pHeight:int):void
		{
			// Créer la vue
			_viewport = new Viewport3D(pWidth, pHeight);
			
			// Créer le moteur de rendu
			_render = new BasicRenderEngine();
			
			// Créer la scène
			_scene = new Scene3D();
			
			// Ajouter la vue
			this.addChild(_viewport);
			
			// Le center
			_center = new DisplayObject3D();
			_center.x = 0;
			_center.y = 0;
			_center.z = 0;
		}
		
		// Créer une caméra
		public function createCamera (pFov:Number = 60, pNear:Number = 10, pFar:Number = 5000, pUseCulling:Boolean = false, pUseProjection:Boolean = false):void
		{
			addCamera(new Camera3D(pFov, pNear, pFar, pUseCulling, pUseProjection));
		}
		
		// Ajouter une caméra
		public function addCamera (pCamera:Camera3D):void
		{
			_cameras.push(pCamera);
		}
		
		// Effacer une caméra
		public function deleteCamera (pCamera:Camera3D):void
		{
			var newCams:Array = [];
			var totalCams:int = _cameras.length;
			for (var i:int = 0; i < totalCams; i++)
			{
				if (_cameras[i] != pCamera)
					newCams.push(_cameras[i]);
				else if (_selectedCamera > 0)
					_selectedCamera--;
			}
			_cameras = newCams;
		}
		
		// Démarrer le rendu en continu
		public function startRender ():void
		{
			addEventListener(Event.ENTER_FRAME, update);
		}
		
		// Arrêter le rendu en continu
		public function stopRender ():void
		{
			removeEventListener(Event.ENTER_FRAME, update);
		}
		
		// Actualiser le rendu
		public function update (event:Event = null):void
		{
			if (_cameras.length > 0)
				_render.renderScene(_scene, _cameras[_selectedCamera], _viewport);
		}
	}
}